/**
 * 
 */
package mm.back.dao.impl;

import genericos.dao.exeptions.PersistanceException;
import genericos.dao.exeptions.PersistenceServiceException;

import java.math.BigDecimal;
import java.util.List;

import mm.back.dao.MMAbstractDAO;
import mm.back.dao.ProductoDAO;
import mm.back.entity.Producto;
import mm.back.filtros.ProductosFiltro;
import mm.exceptions.MMGenericException;

import org.hibernate.HibernateException;
import org.hibernate.Query;

/**
 * @author PUSDERKIS
 *
 */
public class ProductoDAOImpl extends MMAbstractDAO implements ProductoDAO {

	/** 
	 * @see mm.back.dao.ProductoDAO#saveProducto(mm.back.entity.Producto)
	 */
	public void saveProducto(Producto prod) throws MMGenericException {
		
		try{
			if (logger.isDebugEnabled()){
				logger.debug("Se intenta guardar el producto...");
			}
			universalHibernateDAO.getHibernateSession().saveOrUpdate(prod);
			if(logger.isDebugEnabled()){
				logger.debug("Producto guardado correctamente. ID: "+prod.getId());
			}
			
		} catch (PersistenceServiceException e) {
			logger.error("Fallo al insertar el producto en la base de datos.",e);
			throw new MMGenericException(e.getMessage(),e);
		} catch (HibernateException e) {
			logger.error("Fallo al insertar el producto en la base de datos.",e);
			throw new MMGenericException(e.getMessage(),e);
		} catch (PersistanceException e) {
			logger.error("Fallo al insertar el producto en la base de datos.",e);
			throw new MMGenericException(e.getMessage(),e);
		}
		
	}

	/** 
	 * @see mm.back.dao.ProductoDAO#getProductos(java.lang.Boolean)
	 */
	@SuppressWarnings("unchecked")
	public List<Producto> getProductos(Boolean activo)
			throws MMGenericException {
		
		StringBuffer sb = new StringBuffer();
		
		sb.append("FROM Producto p");
		
		if (activo != null){
			
			sb.append(" WHERE p.activo = :activo ");
			if (activo == true){
				sb.append(" and p.rubro.activo = :activo ");
			}
		}
		
		try{
			if (logger.isDebugEnabled()){
				logger.debug("Se intentara cargar la lista de productos...");
			}
			
			Query q = universalHibernateDAO.getHibernateSession().createQuery(sb.toString());
			
			if (activo != null){
				q.setBoolean("activo", activo);
			}
			
			List<Producto> pList = (List<Producto>) q.list();
			
			if(logger.isDebugEnabled()){
				logger.debug("Se cargo la lista de productos...");
			}
			
			return pList;
			
		} catch (PersistenceServiceException e) {
			logger.error("Fallo al recuperar la lista de productos de la base de datos.",e);
			throw new MMGenericException(e.getMessage(),e);
		} catch (HibernateException e) {
			logger.error("Fallo al recuperar la lista de productos de la base de datos.",e);
			throw new MMGenericException(e.getMessage(),e);
		} catch (PersistanceException e) {
			logger.error("Fallo al recuperar la lista de productos de la base de datos.",e);
			throw new MMGenericException(e.getMessage(),e);
		}
		
	}

	/** 
	 * @see mm.back.dao.ProductoDAO#getProductos(mm.back.filtros.ProductosFiltro)
	 */
	public List<Producto> getProductos(ProductosFiltro filtro)
			throws MMGenericException {
		

		StringBuffer sb = new StringBuffer();
		
		sb.append("SELECT p FROM Producto p INNER JOIN p.rubro r WHERE 1=1 ");
		
		sb.append(filtro.getWhereClause("p","r"));
		
		
		
		try{
			if (logger.isDebugEnabled()){
				logger.debug("Se intentara cargar la lista de productos...");
			}
			
			Query q = universalHibernateDAO.getHibernateSession().createQuery(sb.toString());
			
			
			filtro.setWhereParameters(q);
			
			@SuppressWarnings("unchecked")
			List<Producto> pList = (List<Producto>) q.list();
			
			if(logger.isDebugEnabled()){
				logger.debug("Se cargo la lista de productos...");
			}
			
			return pList;
			
		} catch (PersistenceServiceException e) {
			logger.error("Fallo al recuperar la lista de productos de la base de datos.",e);
			throw new MMGenericException(e.getMessage(),e);
		} catch (HibernateException e) {
			logger.error("Fallo al recuperar la lista de productos de la base de datos.",e);
			throw new MMGenericException(e.getMessage(),e);
		} catch (PersistanceException e) {
			logger.error("Fallo al recuperar la lista de productos de la base de datos.",e);
			throw new MMGenericException(e.getMessage(),e);
		}
		
	}

	/** 
	 * @see mm.back.dao.ProductoDAO#restarStock(java.lang.Long, java.math.BigDecimal)
	 */
	public Producto restarStock(Long productoId, BigDecimal cantidad)
			throws MMGenericException {
		
		if (cantidad == null || BigDecimal.ZERO.compareTo(cantidad) > 0){
			if (logger.isDebugEnabled()){
				logger.debug("Se intento restar una cantidad invalida a un producto. idProd: "+productoId+" - cantidad: "+cantidad);
			}
			return null;
		}
		
		try{
			if (logger.isDebugEnabled()){
				logger.debug("Se inicia la resta de stock para el producto: "+productoId);
			}
			Producto prod = (Producto) universalHibernateDAO.get(Producto.class, productoId);
			
			BigDecimal resta = prod.getStock().subtract(cantidad);
			
			if (BigDecimal.ZERO.compareTo(resta) > 0){
				throw new MMGenericException("El producto "+prod.getNombre()+"("+prod.getId()+") tiene \"" +
						prod.getStock()+
						"\" unidades disponibles y se quieren quitar del stock \"" + cantidad +
						"\".");
			}
			
			prod.setStock(resta);
			
			
			saveProducto(prod);
			
			return prod;
		} catch (PersistenceServiceException e) {
			logger.error("Fallo al insertar el producto en la base de datos.",e);
			throw new MMGenericException(e.getMessage(),e);
		}
		
	}

	/**
	 * @see mm.back.dao.ProductoDAO#getProducto(java.lang.Long)
	 */
	public Producto getProducto(Long idProducto) throws MMGenericException {

		try{
			if (logger.isDebugEnabled()){
				logger.debug("Se intenta recuperar el producto con id: "+idProducto);
			}
			Producto prod = (Producto) universalHibernateDAO.get(Producto.class, idProducto);
			
			return prod;
		} catch (PersistenceServiceException e) {
			logger.error("Fallo al insertar el producto en la base de datos.",e);
			throw new MMGenericException(e.getMessage(),e);
		}
	}

}
